import { directory_map } from "./constants";
import { pathMapInstance } from "./pathMap";
import type {
  GetRequiredDescribeType,
  IDescribeType,
  RouteRecordRaw,
} from "./types";

/**
 * - 清理文件名，移除 .vue 后缀和自定义后缀
 * @param fileName 文件名
 * @param fileSuffix 文件后缀
 * @param addRouteSuffix 添加路径后缀
 * @returns 处理后的文件名
 */
const cleanFileName = (
  fileName: string,
  fileSuffix: string,
  addRouteSuffix: string,
): string => {
  let cleanName = fileName.replace(".vue", "");

  if (fileSuffix) {
    cleanName = cleanName.replace(
      new RegExp(`${fileSuffix}(?=/|$)`, "g"),
      addRouteSuffix || "",
    );
  }

  // - 将驼峰转换为短横线
  return cleanName.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
};

/**
 * - 转换路径为路由路径
 * @param path 原始路径
 * @param fileSuffix 文件后缀
 * @param addRouteSuffix 添加路径后缀
 * @returns 转换后的路由路径
 */
const transformPath = (
  path: string,
  fileSuffix: string,
  addRouteSuffix: string,
): string => {
  const directory = path.split("/")[2];

  const segments = cleanFileName(
    path.replace(`/src/${directory}/`, "/"),
    fileSuffix,
    addRouteSuffix,
  ).split("/");

  // - 移除倒数第二个段（通常是重复的目录名）
  // console.log("segments: ", segments);
  segments.splice(-2, 1);

  return segments.join("/");
};

/**
 * - 处理路径
 * @param path 路径
 * @param meta 元数据
 * @returns 处理后的路径
 */
const handlePath = (path: string, meta: IDescribeType): string => {
  // console.log("path: ", path);
  // console.log("meta: ", meta);
  //
  if (meta.__path) {
    return meta.__path;
  }

  // - 如果存在父路径，需要处理父子路径拼接
  if (meta.__parentPath) {
    // - 获取父路径对应的目录和组件信息
    const parentDirectory = meta.__parentPath.split(
      "/",
    )[2] as keyof typeof directory_map;
    const { compMeta } = get_component_by_directory(parentDirectory);

    // - 获取父路径的元数据
    const parentMeta = compMeta[meta.__parentPath]?.meta;

    // console.log("parentMeta: ", parentMeta);
    // - 转换父路径（基础路径）
    let parentSegments = transformPath(
      meta.__parentPath,
      parentMeta?.__rmFileSuffix || "",
      parentMeta?.__addRouteSuffix || "",
    );

    // - 如果父路径有props，需要添加到父路径中
    if (parentMeta?.__props) {
      const parentPropsSegment = handleProps(parentMeta.__props);
      if (parentPropsSegment) {
        parentSegments += parentPropsSegment;
      }
    }

    // - 处理当前文件名
    const currentFileName = path.split("/").at(-1) || "";
    const selfSegments = cleanFileName(
      currentFileName,
      meta.__rmFileSuffix || "",
      meta.__addRouteSuffix || "",
    );

    // console.log("selfSegments: ", selfSegments);
    // console.log("parentSegments: ", parentSegments);

    return [parentSegments, selfSegments].join("/");
  }

  // 处理基础路径转换
  let basePath = transformPath(
    path,
    meta.__rmFileSuffix || "",
    meta.__addRouteSuffix || "",
  );

  // 如果存在props，将props参数添加到路径中
  if (meta.__props) {
    const propsSegment = handleProps(meta.__props);
    if (propsSegment) {
      basePath += propsSegment;
    }
  }

  // console.log("basePath: ", basePath);
  return basePath;
};

/**
 * - 清理路径中的动态参数、正则表达式和可选标记
 * @param path 路径
 * @returns 清理后的路径
 */
const cleanPropsInPath = (path: string) => {
  return path
    .replace(/\/:[^(/]+(\([^)]*\))?\??/g, "") // 匹配动态参数，包括可选标记
    .replace(/\/$/, "");
};

/**
 * - 生成路由名称
 * @param path 路径
 * @param meta 元数据
 * @returns 清理后的路由名称
 */
const generateRouteName = (path: string, meta: IDescribeType): string => {
  // - 清理路径中的动态参数、正则表达式和可选标记
  const cleanPath = cleanPropsInPath(path);

  // - 从清理后的路径获取名称
  const pathName = cleanPath.split("/").at(-1);

  // - 如果路径名称存在且有效，使用路径名称
  if (pathName && pathName.trim()) {
    return pathName;
  }

  // - 否则使用标题转换为路由名称格式
  if (meta.title) {
    return meta.title.replace(/\s+/g, "-").toLowerCase();
  }

  // - 最后兜底使用默认名称
  return "home";
};

/**
 * - 处理props
 * @param props props
 * @returns
 */
const handleProps = (props: NonNullable<IDescribeType["__props"]>) => {
  return Object.entries(props)
    .map(([key, value]) => {
      // 布尔值为true时，添加动态路由参数
      if (typeof value === "boolean" && value) {
        return `/:${key}`;
      }

      // 对象类型的处理
      if (typeof value === "object") {
        // 如果有正则表达式，添加带正则的动态参数
        if ("reg" in value && value.reg) {
          return `/:${key}${value.reg}`;
        }
        // 如果有固定值，直接添加到路径中
        else if ("value" in value && value.value) {
          return `/${value.value}`;
        }
      }

      // 其他情况返回空字符串
      return "";
    })
    .filter(Boolean) // 过滤掉空字符串
    .join("");
};

/**
 * - 检查目录是否合规
 * @param directory 目录
 * @returns
 */
const accroud_directory = (directory: string) => {
  const directory_map_key = Object.keys(directory_map);

  if (!directory_map_key.some((start) => directory.startsWith(start))) {
    return false;
  }

  return true;
};

/**
 * - 获取重定向
 * @param meta 元数据
 * @returns 重定向
 */
const get_Route_Redirect = (meta: IDescribeType) => {
  if (meta.__redirect) {
    const { hasPath, getPath, setPath } = path_Map_Manager();

    if (hasPath(meta.__redirect)) {
      return getPath(meta.__redirect);
    }

    // - 获取重定向路径目录
    const redirectPathDirectory = meta.__redirect
      .replace("/src/", "")
      .split("/")[0] as keyof typeof directory_map;
    // console.log("redirectPathDirectory: ", redirectPathDirectory);

    if (accroud_directory(redirectPathDirectory)) {
      const { getFullMeta } = get_component_by_directory(redirectPathDirectory);

      // - 获取重定向组件的完整meta
      const redirectFullMeta = getFullMeta(meta.__redirect);

      // - 获取重定向路径
      // console.log(
      //   "----- redirectFullMeta: ",
      //   meta.__redirect,
      //   redirectFullMeta,
      // );
      const redirectPath = handlePath(meta.__redirect, redirectFullMeta);

      // console.log("redirectPath: ", redirectPath);
      // - 设置重定向
      setPath(meta.__redirect, redirectPath);

      return cleanPropsInPath(redirectPath);
    } else {
      return cleanPropsInPath(meta.__redirect);
    }
  }
  return undefined;
};

/**
 * - 将扁平化路由转换为嵌套路由
 * @param flatRoutes 扁平化路由
 * @returns 嵌套路由
 */
export const transformRoutesToNested = (
  flatRoutes: RouteRecordRaw[],
): RouteRecordRaw[] => {
  // - 创建一个映射来存储路径和路由对象的对应关系
  const pathMap = new Map();

  // - 首先将所有路由放入映射
  flatRoutes.forEach((route) => {
    pathMap.set(route.path, route);
  });
  // console.log("pathMap: ", pathMap);

  const nestedRoutes: RouteRecordRaw[] = [];

  // - 遍历所有路由进行嵌套处理
  flatRoutes.forEach((route) => {
    const currentRoute = pathMap.get(route.path);

    // - 如果路径包含'/'且不是根路径
    if (route.path.includes("/") && route.path !== "/") {
      // - 找到父路径
      const parentPath = route.path.substring(0, route.path.lastIndexOf("/"));
      const parentRoute =
        pathMap.get(parentPath) || pathMap.get(parentPath + "/");

      if (parentRoute) {
        // - 将当前路由添加到父路由的children中，使用相对路径
        parentRoute.children.push({
          ...currentRoute,
          path: route.path.substring(parentPath.length + 1), // 裁剪父路径部分
        });
      } else {
        // - 如果没有父路由，直接添加到根
        nestedRoutes.push(currentRoute);
      }
    } else {
      // - 根路径路由直接添加到结果
      nestedRoutes.push(currentRoute);
    }
  });

  // - 清理空的children数组
  const cleanChildren = (routes: RouteRecordRaw[]): RouteRecordRaw[] => {
    // console.log("cleanChildren: ", routes);
    return routes.map((route) => {
      if (route.children && route.children.length === 0) {
        delete route.children;
        return route;
      }
      // console.log("----route: ", route);
      // 只有当 children 存在且有内容时才递归处理
      if (route.children && route.children.length > 0) {
        return {
          ...route,
          children: cleanChildren(route.children),
        };
      }
      // 如果没有 children 或 children 为空，直接返回路由对象
      return route;
    });
  };

  // console.log("nestedRoutes: ", nestedRoutes);
  return cleanChildren(nestedRoutes);
};

/**
 * - 运行时态下：获取views目录下的所有子目录的指定说明文件的导出内容
 * @param {string} directory 目录
 * @returns
 */
const get_component_by_directory = (directory: keyof typeof directory_map) => {
  // - 获取组件内容
  const { compContent, components } = directory_map[directory]();

  // - 过滤出符合条件的meta文件
  const compMeta = Object.fromEntries(
    Object.entries(compContent).filter(
      ([_, value]) => value.meta !== undefined && value.meta.__isRouteComponent,
    ),
  );

  /**
   * - 获取完整的meta信息
   * @param fullPath 组件路径
   * @returns 完整的meta信息
   */
  const getFullMeta = (fullPath: string): IDescribeType => {
    // - 返回meta
    return compMeta[fullPath]?.meta as IDescribeType;
  };

  /**
   * - 获取路由所需的meta
   * @param compPath 组件路径
   * @returns 路由所需的meta
   */
  const getRouteMeta = (compPath: string): GetRequiredDescribeType => {
    const meta = compMeta[compPath]?.meta as IDescribeType;

    return Object.fromEntries(
      Object.entries(meta).filter(([key]) => !key.startsWith("__")),
    ) as GetRequiredDescribeType;
  };

  // - 将meta文件转换为对象
  return {
    compMeta,
    components,
    getRouteMeta,
    getFullMeta,
  };
};

// * 路径管理器
const path_Map_Manager = () => {
  const setPath = (path: string, routePath: string) => {
    pathMapInstance.set(path, routePath);
  };

  const getPath = (path: string) => {
    return pathMapInstance.get(path);
  };

  const hasPath = (path: string) => {
    return pathMapInstance.has(path);
  };

  const getAll = () => {
    return pathMapInstance;
  };

  return {
    setPath,
    getPath,
    hasPath,
    getAll,
  };
};

/**
 * - 获取对应目录下所有符合要求的vue文件 转换后 的路由配置表
 * @param {string} directory 目录
 * @returns
 */
export const get_Routes = (directory: keyof typeof directory_map) => {
  // - 运行时态下：获取views目录下的所有子目录的defineOptions内容以及组件本身
  const { compMeta, components, getFullMeta, getRouteMeta } =
    get_component_by_directory(directory);

  // - 路由列表
  const routes: RouteRecordRaw[] = [];

  Object.entries(compMeta).forEach(([key]) => {
    // console.log(key, value);

    // - 路径管理器
    const { hasPath, setPath, getPath } = path_Map_Manager();

    // - 获取完整meta
    const fullMeta = getFullMeta(key);
    // console.log("fullMeta: ", fullMeta);

    // - 获取路径
    // ? 如果路径已存在，则直接获取，否则需要处理路径
    const path = hasPath(key)
      ? getPath(key) || handlePath(key, fullMeta)
      : handlePath(key, fullMeta);

    // ? 将路径和路由路径进行映射
    setPath(key, path);

    // - 获取名称
    const name = generateRouteName(path, fullMeta);

    // - 获取路由meta
    const routeMeta = getRouteMeta(key);

    // - 组件
    const component = components[key];

    // - 获取重定向
    const redirect = get_Route_Redirect(fullMeta);

    // - 获取子路由
    const children = fullMeta.__children;

    // console.log("path: ", path);
    // console.log("name: ", name);
    // console.log("compPath: ", compPath);
    // console.log("compFileName: ", compFileName);
    // console.log("component: ", component);
    // console.log("redirect: ", redirect);

    // - 当前路由对象
    const currentRoute: RouteRecordRaw = {
      path,
      name,
      component,
      meta: routeMeta,
      children: children || [],
    };

    // - 设置重定向
    redirect && (currentRoute.redirect = redirect);

    routes.push(currentRoute);
  });

  // console.log("pathMapInstance: ", pathMapInstance);

  return routes;
};
